Gestión de actas de la Junta Directiva (BORRADOR)

En las actas deben reflejarse los siguientes datos: fecha, hora y lugar de la reunión, orden del día, asistentes, breve extracto de los debates, y acuerdos adoptados.

Las decisiones de la Junta Directiva deben ser públicas y documentadas por escrito. No obstante puede haber datos sensibles en las actas, como DNIs, direcciones, etc., que no conviene publicar de forma abierta.

WorkFlow de actas

  1. Las actas se elaboran en el repositorio privado de la asociación, accesible por la Junta Directiva.

  2. Todas las actas incluyen una marca no visible, con el formato ”.. Nonce: valores aleatorios”. Esos valores deben ser únicos e impredecibles para cada acta. Debería tener una entropía mínima de 256 bits.

    Jesús Cea, por ejemplo, genera cuatro valores de 65.5 bits usando el comando:

    $ python /z-clave.py
    

    totalizando 262 bits de entropía.

    Los usuarios de entornos Unix/Linux pueden hacer algo del estilo de:

    $ dd if=/dev/urandom count=9999 | sha256sum -
    

    Nota

    El “nonce” no se exporta a las actas públicas. El objetivo es que teniendo las actas públicas “expurgadas” y el hash del acta privada, que no se puedan deducir datos expurgados mediante prueba y error, hasta que hacemos coincidir el hash.

    Por ejemplo, si el acta pone “Jesús Cea, con DNI CONFIDENCIAL”, y tenemos el hash del acta original, podemos generar números de DNI aleatorios hasta encontrar uno que, puesto en el documento, nos proporciona el hash correcto.

    Dado que el “nonce” añade al menos 256 bits de entropía, y el “nonce” no se hace público, eliminamos este ataque.

  3. Los datos considerados confidenciales deben aparecer en una línea por sí mismos. El objetivo es que la Junta Directiva pueda verificar de un vistazo, con un diff, que ambas actas son exactamente iguales, salvo por la eliminación de los datos confidenciales.

  4. Una vez que el acta está completa y se considera final, se hace una copia. En dicha copia se eliminan los datos confidenciales y se sustituyen por los caracteres *CONFIDENCIAL*. También se elimina el “nonce”.

  5. En la copia del acta se añade el hash SHA1 del acta original.

  6. Se verifica, mediante diff, que los únicos cambios entre el acta original y su copia son: El reemplazo de datos confidenciales, la eliminación del “nonce” y la adición del SHA1 del acta original.

  7. La copia del acta, así expurgada, se copia al repositorio público, en la sección de actas no firmadas.

  8. En principio, las actas no se modifican. Pero mientras el acta no se firma, puede sufrir alteraciones. Si se modifica el acta original, debe repetirse el proceso de exportación.

  9. Una vez que el acta original se firma y se hace inmutable, se mueve su copia pública a la sección de actas firmadas.

Firma digital de actas

Nota

Los motivos para utilizar firmas digitales son los siguientes:

  • Los miembros de la Junta Directiva están físicamente distribuídos.

  • La mayoría de las reuniones de la Junta Directiva se realizan online.

  • Se pretende que la gestión de papel sea mínima.

  • La obtención de un certificado de la FNMT o el uso del DNI electrónico es sencillo, rápido y gratuito.

    En este momento se admiten certificados de la FNMT y DNIe.

  • Se pretende que la firma electrónica tenga valor legal.

  • Python España es una asociación interesada en promover el uso de la tecnología para mejorar los procesos y la seguridad online.

  • Una vez consensuado el documento a firmar, el secretario calcula su hash SHA1, y escribe un documento de texto UTF-8 puro, en formato UNIX (las líneas se terminan con un \n, o ASCII 10).

    Por la presente certifico que el documento con hash SHA1 xxxxxxxxxxxxxxxxxxxx es válido y se ajusta a la verdad.

  • Dicho fichero se almacena en el repositorio privado de la asociación.

  • Todos los miembros de la Junta Directiva firman dicho documento.

  • Las firmas se verifican como correctas, y se añaden al repositorio privado de la asociación.

    Advertencia

    Bajo ningún concepto debe añadirse una firma al repositorio sin haber verificado su identidad y su corrección.

Generación de firmas digitales mediante OpenSSL

Advertencia

¡SECCIÓN A MEDIO ESCRIBIR!

Si tenemos el certificado en un fichero PKCS#12 llamado “certificado.pkcs12”, y el documento a firmar en “DOCUMENTO_ORIGINAL”, la firma se realiza de la siguiente manera:

Exportamos el certificado en firefox, como PKCS#12.

Convertimos ese certificado a una clave usable: (no incluye certificado de la CA)

openssl pkcs12 -in fnmt.p12 -out keyStore.pem -clcerts

Si incluimos los certificados de la CA, hay que hacerlo en el orden correcto. Para ello hacemos algo del estilo:

openssl pkcs12 -in fnmt.p12 -out keyStore.pem -clcerts openssl pkcs12 -in fnmt.p12 -out keyStore2.pem -cacerts -nokeys cat keyStore2.pem >>keyStore.pem

Nos pedirá tanto la clave de exportación PKCS#12 como una clave para proteger el PEM final.

Generamos una firma SMIME con:

openssl smime -sign -in z2 -text -out z -signer /tmp/keyStore.pem

Verificamos la firma con:

openssl smime -verify -in z -CAfile CA.crt

Generamos una firma PKCS#7 con:

openssl smime -sign -in z2 -text -signer /tmp/keyStore.pem | openssl smime -pk7out >z

¿Cómo la verificamos?????

GENERAMOS UNA FIRMA INCLUYENDO EL TEXTO ORIGINAL EN EL FICHERO DE FIRMA. El “-nodetach” genera un PKCS#7, no un SMIME, y lo genera con el texto firmado dentro.

openssl smime -sign -nodetach -in z2 -out z -outform pem -signer /tmp/keyStore.pem

Verificamos con

openssl smime -verify -in z -CAfile CA.crt -inform PEM

Esto funciona, pero no quiero incluir el texto original.

Si no incluyo el “-nodetach”, entonces el texto de entrada se puede verificar bien SIEMPRE Y CUANDO este normalizado con “\r\n”.

Algo del estilo:

openssl smime -sign -in z2 -out z -outform pem -signer /tmp/keyStore.pem

Verificado con:

openssl smime -verify -in z -CAfile CA.crt -inform PEM -content z3

donde “z3” es “z2” con los “\n” convertidos a “\r\n”.

Para que no ocurra esa normalización, podemos hacer:

openssl smime -sign -in z2 -out z -outform pem -binary -signer /tmp/keyStore.pem

Y verificamos con

openssl smime -verify -in z -CAfile CA.crt -inform PEM -content z2

Para normalizar de \n a \r\n, podemos usar

awk ‘sub(“$”, “r”)’

Advertencia

¡SECCIÓN A MEDIO ESCRIBIR!

Verificación de las firmas digitales

Para verificar las firmas digitales, es necesario tener descargados los certificados raíz de la FNMT y del DNIe. Almacenamos ambos certificados concatenados en un único fichero, llamado CA.crt.

Nota

Si no tenemos los certificados aún, hacemos lo que sigue. Naturalmente esto solo hay que hacerlo la primera vez.

  • Descargamos el certificado de la FNMT. El fichero descargado se llama FNMTClase2CA.cer.

  • Convertimos el certificado a formato PEM:

    $ openssl x509 -inform DER -outform PEM \
      -in FNMTClase2CA.cer \
      -text -fingerprint > CA.crt
    
  • Descargamos el certificado del DNI electrónico. El fichero descargado se llama ACRAIZ-SHA2.zip.

  • Convertimos el certificado a formato PEM y lo concatenamos al fichero de entidades de certificación reconocidas:

    $ unzip -x ACRAIZ-SHA2.zip
    $ openssl x509 -inform DER -outform PEM \
      -in ACRAIZ-SHA2.crt \
      -text -fingerprint >> CA.crt
    
  • Ahora tenemos las entidades de certificación reconocidas en el fichero CA.crt. Conservamos dicho fichero.

  • Normalizamos el documento original:

    $ tr -d "\r" < DOCUMENTO_ORIGINAL | \
      awk 'sub("$", "\r")' > DOCUMENTO_ORIGINAL_NORMALIZADO
    

    Nota

    Este paso convierte los \n de Unix a \r\n de MS-DOS.

    Esto es necesario porque OpenSSL y Firefox normalizan el texto a ese formato.

    En realidad opino que es un bug de OpenSSL, porque si normaliza al firmar, debería normalizar también al verificar, a menos que se incluya -binary.

  • Verificamos la firma electrónica:

    $ openssl smime -verify -CAfile CA.crt -inform PEM \
      -content DOCUMENTO_ORIGINAL_NORMALIZADO \
      -in FIRMA.pkcs7
    
  • Si la firma es correcta, vemos la identidad del usuario que firma:

    $ openssl pkcs7 -inform PEM -print_certs -noout \
      -in FICHERO.pkcs7
    

    Nota

    Este comando nos indica la “presunta” identidad de la firma, pero no la verifica. La integridad de la firma, y que esta ha sido generada con un certificado válido, se realiza en el comando previo.

  • Si nos interesase verificar la fecha de la firma, podemos hacer algo como:

    $ openssl asn1parse -in FICHERO.pkcs7
    

    y ahí buscamos el UTCTIME inmediatamente despues de :signingTime. Una fecha como :130301025426Z significa “2013-03-01 02:54:26”. La zona horaria es UTC/GMT (una hora de diferencia en invierno y dos horas en verano, respecto a la España peninsular).